package com.example.demo.redis;

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Redis 分布式锁：利用 Redission
 * 核心加锁逻辑：
 * RLock lock = redisson.getLock(lockKey);
 *
 * try{
 *     lock.lock();
 *
 * } finally {
 *    //一定要释放
 *    lock.unlock();
 * }
 *
 *
 * 模拟场景：
 * Pod1: 8080   url :  http://localhost:8080/stock/sync
 * <p>
 * Pod2: 8081   url :  http://localhost:8081/stock/sync
 * IDEA  配置：  VM-Option: -Dserver.port=8081
 */
@RestController
public class IndexController_Redission {

    @Autowired
    private Redisson redisson;

    @Autowired
    private StringRedisTemplate redisTemplate;


    @RequestMapping("/redissonLock/reduceStock")
    public String reduceStock() {

        String lockKey = "product_01";

       /*String versionId = UUID.randomUUID().toString();

        Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, versionId, 30, TimeUnit.SECONDS);

        if (!result) {
            return "error_错误";
        }*/

        RLock lock = redisson.getLock(lockKey);

        String msg = "";
        try {
            lock.lock();
            int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
            if (stock > 0) {
                int realStock = stock - 1;
                redisTemplate.opsForValue().set("stock", realStock + "");
                msg = "减库存成功，剩余:" + realStock;
                System.out.println(msg);
            } else {
                msg = "减库存失败，库存不足";
                System.out.println(msg);
            }
        } finally {
            //判断如果是自己加的锁，就释放
           /* if(versionId.equals(redisTemplate.opsForValue().get(lockKey))){
                redisTemplate.delete(lockKey);
            }*/

            lock.unlock();
        }
        return msg;
    }

}
